﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TechTalk.SpecFlow;
using MethodWorx.CMS.Content;
using Moq;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MethodWorx.CMS.UI.Models;
using MethodWorx.CMS.UI.Controllers;
using MethodWorx.Core.DomainModel;
using MethodWorx.CMS.UI.Models.Shared;
using System.ComponentModel.DataAnnotations;

namespace MethodWorx.CMS.UI.Tests.MasterPages
{
    [Binding]
    public class ModelSteps
    {
        private static void ValidateViewModel<VM, C>(VM viewModelToValidate, C controller) where C : Controller
        {
            var validationContext = new ValidationContext(viewModelToValidate, null, null);
            var validationResults = new List<ValidationResult>();
            Validator.TryValidateObject(viewModelToValidate, validationContext, validationResults, true);
            foreach (var validationResult in validationResults)
            {
                controller.ModelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage);
            }
        }


        PageTemplate [] pageTemplateSource;
        IPageTemplateRepository pageTemplates = new PageTemplateRepository(new PageTemplate[] { }.AsQueryable());
        ActionResult result;
        PageTemplateBasicDetails details = new PageTemplateBasicDetails();
        StubUnitOfWorkFactory uowFactory = new StubUnitOfWorkFactory();
        PageTemplate created;

        [Given(@"Master pages exists")]
        public void GivenMasterpagesexists()
        {
            this.pageTemplateSource = new PageTemplate[]
            {
                new PageTemplate() { Id = Guid.NewGuid(), Name = "Template 1", Abstract = true },
                new PageTemplate() { Id = Guid.NewGuid(), Name = "Template 2", Abstract = true }
            };
            //  setup the page templates
            this.pageTemplates = new PageTemplateRepository(this.pageTemplateSource.AsQueryable());
        }

        [Then(@"I should see the master page view")]
        public void ThenIShouldSeeTheMasterPageView()
        {
            TestHelper.AssertIsViewResult(this.result, "Create");
        }

        [Then(@"The Master drop down should contain all master pages")]
        public void ThenTheMasterDropDownShouldContainAllMasterPages()
        {
            TestHelper.AssertDropDownContainsItems<CreateAbstractPageTemplateModel, PageTemplate>(
                this.result,
                m => m.PageTemplateBasicDetails.ParentsSelectList,
                this.pageTemplateSource,
                (sli, pt) => sli.Text == pt.Name && sli.Value == pt.Id.ToString());
                
        }

        [When(@"I open create master page")]
        public void WhenIOpenCreateMasterPage()
        {
            var controller = this.CreateSystemUnderTest();
            this.result = controller.Create(null, true);
        }

        private AbstractPageTemplateController CreateSystemUnderTest()
        {
            var controller = new AbstractPageTemplateController(uowFactory, this.pageTemplates, new ContentTemplateRepository(new ContentTemplate[] { }.AsQueryable()));
            return controller;
        }

        [Given(@"I am creating a master page")]
        public void GivenIAmCreatingAMasterPage()
        {

            var controller = this.CreateSystemUnderTest();
            this.result = controller.Create(null, true);
        }

        [Given(@"no value is entered for name")]
        public void GivenNoValueIsEnteredForName()
        {
            details.Name = "";
        }

        [Then(@"I should see the error message (.*)")]
        public void ThenIShouldSeeTheErrorMessage(string message)
        {
            TestHelper.AssertResultContainsError(this.result, message);
        }

        [When(@"I attempt to create a master page")]
        public void WhenIAttemptToCreateAMasterPage()
        {
            var controller = this.CreateSystemUnderTest();
            ValidateViewModel<PageTemplateBasicDetails, AbstractPageTemplateController>(this.details, controller);
            this.result = controller.Create(null, this.details, "save", true);
        }

        [Given(@"I enter a value in the name field")]
        public void GivenIEnterAValueInTheNameField()
        {
            details.Name = "AValue";
        }

        [Then(@"a master page should be created")]
        public void ThenAMasterPageShouldBeCreated()
        {
            Assert.IsTrue(
                this.uowFactory.UnitsOfWork.Where(
                    u => u.IsCommited == true &&
                    u.Added.OfType<PageTemplate>().Any()).Any(), "Master Page Template Was not Created");
        }

        [Then(@"the name should be saved")]
        public void ThenTheNameShouldBeSaved()
        {
            Assert.IsTrue(
                this.uowFactory.UnitsOfWork.Where(
                    u => u.IsCommited == true &&
                    u.Added.OfType<PageTemplate>().FirstOrDefault(pt => pt.Name == this.details.Name) != null).Any(), "Master Page Template Was not Created");
        }

        [Given(@"I enter a value in the description field")]
        public void GivenIEnterAValueInTheDescriptionField()
        {
            this.details.Description = "SomeDescription";
        }

        [Then(@"the description should be saved")]
        public void ThenTheDescriptionShouldBeSaved()
        {
            Assert.IsTrue(
              this.uowFactory.UnitsOfWork.Where(
                  u => u.IsCommited == true &&
                  u.Added.OfType<PageTemplate>().FirstOrDefault(pt => pt.Description == this.details.Description) != null).Any(), "Master Page Template Was not Created");
        }
    }
}
